package com.itheima.api;

import com.itheima.domain.Friend;
import com.itheima.domain.Movement;
import com.itheima.domain.MovementTimeLine;
import com.itheima.util.IdWorker;
import com.itheima.vo.PageResult;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.checkerframework.checker.units.qual.C;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Async;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;


@DubboService
public class MovementApiImpl implements MovementApi {

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private IdWorker idWorker;

    /**
     * 发布动态
     *
     * @param movement
     */
    @Async
    @Override
    public void publish(Movement movement) {
        movement.setPid(idWorker.getNextId("movement"));
        //保存数据到movement表
        mongoTemplate.save(movement);
        //查询friend表
        Long userId = movement.getUserId();
        Query query = Query.query(Criteria.where("userId").is(userId));
        List<Friend> friends = mongoTemplate.find(query, Friend.class);

        //将数据保存到时间线表
        for (Friend friend : friends) {
            MovementTimeLine timeLine = new MovementTimeLine();
            timeLine.setMovementId(movement.getId());
            timeLine.setUserId(friend.getUserId());
            timeLine.setFriendId(friend.getFriendId());
            timeLine.setCreated(System.currentTimeMillis());
            mongoTemplate.save(timeLine);
        }
    }

    /**
     * 根据id查询动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    @Override
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        long count = mongoTemplate.count(query, Movement.class);
        //分页查询
        query.limit(pagesize).skip((long) (page - 1) * pagesize)
                .with(Sort.by(Sort.Order.desc("created")));
        List<Movement> movements = mongoTemplate.find(query, Movement.class);
        return new PageResult(page, pagesize, (int) count, movements);
    }

    /**
     * 查询好友动态
     *
     * @param page
     * @param pagesize
     * @param friendId
     * @return
     */
    @Override
    public List<Movement> getFriendMovements(Integer page, Integer pagesize, Long friendId) {
        //通过friendId查询动态id
        Query query = Query.query(Criteria.where("friendId").is(friendId))
                .skip((long) (page - 1) * pagesize).limit(pagesize).with(Sort.by(Sort.Order.desc("created")));
        List<MovementTimeLine> movementTimeLines = mongoTemplate.find(query, MovementTimeLine.class);
        List<ObjectId> movementIds = movementTimeLines.stream().map(MovementTimeLine::getMovementId).collect(Collectors.toList());
        //通过动态id查询具体动态信息
        Query movementQuery = Query.query(Criteria.where("id").in(movementIds));
        return mongoTemplate.find(movementQuery, Movement.class);
    }

    /**
     * 查询推荐动态
     *
     * @param pids
     * @return
     */
    @Override
    public List<Movement> getRecommend(List<Long> pids) {
        Query query = Query.query(Criteria.where("pid").in(pids)).with(Sort.by(Sort.Order.desc("created")));
        return mongoTemplate.find(query, Movement.class);
    }

    /**
     * 获取随机动态
     *
     * @return
     */
    @Override
    public List<Movement> getRandom(int counts) {
        //1、创建统计对象，设置统计参数
        TypedAggregation aggregation = Aggregation.newAggregation(Movement.class,Aggregation.sample(counts));
        //2、调用mongoTemplate方法统计
        AggregationResults<Movement> results = mongoTemplate.aggregate(aggregation, Movement.class);
        //3、获取统计结果
        return results.getMappedResults();
    }

    /**
     * 根据动态id查询动态信息
     * @param id
     * @return
     */
    @Override
    public Movement getMovementById(String id) {
        return mongoTemplate.findById(id, Movement.class);
    }

}
